#pragma once

#include "../GameObject.h"
#include <vector>

class Player;
typedef std::shared_ptr<Player> PlayerPtr;

class Item;
typedef std::shared_ptr<Item> ItemPtr;

class Character : public GameObject
{
public:
	enum Sex
	{
		HE = 0,
		SHE,
		IT
	};

	enum BodyPart
	{
		BODYPART_ERROR = 0,
		HEAD = 1,
		THROAT = 2,
		LEFT_ARM = 4,
		RIGHT_ARM = 8,
		CHEST = 16,
		STOMACK = 32,
		SPINE = 64,
		GROIN = 128,
		LEFT_LEG = 256,
		RIGHT_LEG = 512,
		LEFT_FOOT = 1024,
		RIGHT_FOOT = 2048
	};

	Character(const std::string &name, const std::string &description, Character::Sex sex = Character::HE, 
				unsigned int bodyparts = HEAD|THROAT|LEFT_ARM|RIGHT_ARM|CHEST|STOMACK|SPINE|GROIN|LEFT_LEG|RIGHT_LEG|LEFT_FOOT|RIGHT_FOOT,
				unsigned int weight = 70);
	virtual ~Character();

	void look() override;
	void examine() override;

	bool hasPlayer() const { return player != nullptr; }
	void setPlayer(const PlayerPtr &player) { this->player = player; }
	const PlayerPtr &getPlayer() const { return player; }

	//Inventory
	void add(const ItemPtr &item);
	void remove(const ItemPtr &item);
	const std::vector<ItemPtr> &getItems() const { return items; }

	bool canHandleCommand(const CommandPtr &command) override;

	bool hold(const ItemPtr &item);
	bool wield(const ItemPtr &item);
	ItemPtr removeItemInHand();
	const ItemPtr &getHeldItem() const { return held_item; }

	Character::Sex getSex() const { return sex; }
	std::string getSexAsString() const;

	enum Stance
	{
		LAYING = 0,
		SLEEPING,
		RESTING,
		SITTING,
		FLYING,
		STANDING,
		UNCONSCIOUS
	};
	Character::Stance getStance() const { return stance; }
	std::string getStanceAsString();
	void setStance(Character::Stance stance) { this->stance = stance; }

	BodyPart getRandomBodypart(int seed = -1, int call_count = 0) const;
	static std::string getBodypartName(BodyPart bodypart);

protected:
	PlayerPtr player;
	std::vector<ItemPtr> items;

	ItemPtr held_item;

	Character::Sex sex;
	unsigned int bodyparts;

	Character::Stance stance;
};
typedef std::shared_ptr<Character> CharacterPtr;
